import { type RouterHistory, type RouteRecordRaw, type RouteComponent, createWebHistory, createWebHashHistory } from "vue-router";
import { router } from "./index";
import { isProxy, toRaw } from "vue";
import { useTimeoutFn } from "@vueuse/core";
import { cloneDeep, isAllEmpty, intersection, storageLocal } from "@pureadmin/utils";
import { getConfig } from "@/config";
import type { menuType } from "@/layout/types";
import { buildHierarchyTree } from "@/utils/tree";
import { userKey, type DataInfo } from "@/utils/auth";
import { useMultiTagsStoreHook } from "@/store/modules/multiTags";
import { usePermissionStoreHook } from "@/store/modules/permission";
import { $t } from "@/plugins/i18n";
import { home } from "@/router/enums";
import { viceMenus } from "./viceMenusConstant";

const modulesRoutes = import.meta.glob("/src/views/**/*.{vue,tsx}");
const IFrame = () => import("@/layout/frameView.vue");
const Layout = () => import("@/layout/index.vue");

const otherPages = ["fullScreen"];

function handRank(routeInfo: any) {
  const { name, path, parentId, meta } = routeInfo;
  return isAllEmpty(parentId) ? (isAllEmpty(meta?.rank) || (meta?.rank === 0 && name !== "Home" && path !== "/") ? true : false) : false;
}

/** 按照路由中meta下的rank等级升序来排序路由 */
function ascending(arr: any[]) {
  arr.forEach((v, index) => {
    // 当rank不存在时，根据顺序自动创建，首页路由永远在第一位
    if (handRank(v)) v.meta.rank = index + 2;
  });
  return arr.sort((a: { meta: { rank: number } }, b: { meta: { rank: number } }) => {
    return a?.meta.rank - b?.meta.rank;
  });
}

/** 过滤meta中showLink为false的菜单 */
function filterTree(data: RouteComponent[]) {
  const newTree = cloneDeep(data).filter((v: { meta: { showLink: boolean } }) => v.meta?.showLink !== false);
  newTree.forEach((v: { children }) => v.children && (v.children = filterTree(v.children)));
  return newTree;
}

/** 过滤children长度为0的的目录，当目录下没有菜单时，会过滤此目录，目录没有赋予roles权限，当目录下只要有一个菜单有显示权限，那么此目录就会显示 */
function filterChildrenTree(data: RouteComponent[]) {
  const newTree = cloneDeep(data).filter((v: any) => v?.children?.length !== 0);
  newTree.forEach((v: { children }) => v.children && (v.children = filterTree(v.children)));
  return newTree;
}

/** 判断两个数组彼此是否存在相同值 */
function isOneOfArray(a: Array<string>, b: Array<string>) {
  return Array.isArray(a) && Array.isArray(b) ? (intersection(a, b).length > 0 ? true : false) : true;
}

/** 从localStorage里取出当前登陆用户的角色roles，过滤无权限的菜单 */
function filterNoPermissionTree(data: RouteComponent[]) {
  const currentRoles = storageLocal().getItem<DataInfo<number>>(userKey)?.roles ?? [];
  const newTree = cloneDeep(data).filter((v: any) => isOneOfArray(v.meta?.roles, currentRoles));
  newTree.forEach((v: any) => v.children && (v.children = filterNoPermissionTree(v.children)));
  return filterChildrenTree(newTree);
}

/** 通过指定 `key` 获取父级路径集合，默认 `key` 为 `path` */
function getParentPaths(value: string, routes: RouteRecordRaw[], key = "path") {
  // 深度遍历查找
  function dfs(routes: RouteRecordRaw[], value: string, parents: string[]) {
    for (let i = 0; i < routes.length; i++) {
      const item = routes[i];
      // 返回父级path
      if (item[key] === value) return parents;
      // children不存在或为空则不递归
      if (!item.children || !item.children.length) continue;
      // 往下查找时将当前path入栈
      parents.push(item.path);

      if (dfs(item.children, value, parents).length) return parents;
      // 深度遍历查找未找到时当前path 出栈
      parents.pop();
    }
    // 未找到时返回空数组
    return [];
  }

  return dfs(routes, value, []);
}

/** 查找对应 `path` 的路由信息 */
function findRouteByPath(path: string, routes: RouteRecordRaw[]) {
  let res = routes.find((item: { path: string }) => item.path == path);
  if (res) {
    return isProxy(res) ? toRaw(res) : res;
  } else {
    for (let i = 0; i < routes.length; i++) {
      if (routes[i].children instanceof Array && routes[i].children.length > 0) {
        res = findRouteByPath(path, routes[i].children);
        if (res) {
          return isProxy(res) ? toRaw(res) : res;
        }
      }
    }
    return null;
  }
}

function addPathMatch() {
  if (!router.hasRoute("pathMatch")) {
    router.addRoute({
      path: "/:pathMatch(.*)*",
      name: "pathMatch",
      component: () => import("@/views/error/404.vue")
    });
  }
}

/** 处理动态路由（后端返回的路由） */
function handleAsyncRoutes(routeList) {
  if (routeList.length === 0) {
    usePermissionStoreHook().handleWholeMenus(routeList);
  } else {
    formatFlatteningRoutes(addAsyncRoutes(routeList)).map((v: RouteRecordRaw) => {
      // 防止重复添加路由
      if (router.options.routes[0]?.children && router.options.routes[0]?.children?.findIndex(value => value.path === v.path) !== -1) {
        return;
      } else {
        // 切记将路由push到routes后还需要使用addRoute，这样路由才能正常跳转
        if (!router.options?.routes[0]?.children) {
          router.options.routes[0].children = [];
        }
        if (otherPages.some(item => v.path.includes(item))) {
          router.options?.routes?.push(v);
        } else {
          router.options.routes[0]?.children?.push(v);
        }
        // router.options.routes[0]?.children?.push(v);
        // 最终路由进行升序
        ascending(router.options.routes[0].children);
        if (!router.hasRoute(v?.name)) router.addRoute(v);
        let flattenRouters: any = router.getRoutes().find(n => n.path === "/");
        flattenRouters && router.addRoute(flattenRouters);
      }
    });
    usePermissionStoreHook().handleWholeMenus(routeList);
  }
  addPathMatch();
  // const rrr = router.getRoutes();
  // console.log("rrr: ", rrr);
}

/** 初始化路由（`new Promise` 写法防止在异步请求中造成无限循环）*/
function initRouter(data?: any) {
  const routes = data?.length ? mapAsyncRoutes(data) : [];
  if (getConfig()?.CachingAsyncRoutes) {
    // 开启动态路由缓存本地localStorage
    const key = "async-routes";
    const asyncRouteList = storageLocal().getItem(key) as any;
    if (asyncRouteList && asyncRouteList?.length > 0) {
      return new Promise(resolve => {
        handleAsyncRoutes(asyncRouteList);
        resolve(router);
      });
    } else {
      return new Promise(resolve => {
        handleAsyncRoutes(cloneDeep(routes));
        storageLocal().setItem(key, routes);
        resolve(router);
      });
    }
  } else {
    return new Promise(resolve => {
      handleAsyncRoutes(cloneDeep(routes));
      resolve(router);
    });
  }
}

/**
 * @description: 初始化根路由
 * @param {*} routes
 * @return {*}
 */
function initRootRouter(routes) {
  let hasRootPath: any = router.getRoutes().some(n => n.path === "/");
  if (!hasRootPath) {
    let redirectPath = routes[0].path;
    const h = {
      path: "/",
      name: "Root",
      component: Layout,
      redirect: redirectPath,
      meta: {
        icon: "homeFilled",
        title: $t("menus.hshome"),
        rank: home,
        hiddenTag: true,
        backstage: true
      },
      children: [routes[0]]
    };
    router.options?.routes?.unshift(h);
    if (!router.hasRoute(h?.name)) router.addRoute(h);
  }
}

/**
 * 将多级嵌套路由处理成一维数组
 * @param routesList 传入路由
 * @returns 返回处理后的一维路由
 */
function mapAsyncRoutes(data: any) {
  return data.map(item => formatRoute(item));
}

/**
 * @description: 路由格式化
 * @param {any} item
 * @return {*}
 */
const formatRoute = (item: any) => {
  const viceMenu = getViceMenu(item);
  const routeData = {
    name: item.name,
    path: item.path,
    redirect: item.redirect,
    component: item.component,
    meta: {
      title: item.title,
      icon: item.icon,
      activeMenu: item.activeMenu,
      showLink: !item.isHide,
      keepAlive: item.isKeepAlive,
      isFull: item.isFull,
      viceMenu
    },
    children: item.children
  };
  if (item.children?.length) {
    routeData.children = item.children.filter(r => r.component).map(r => formatRoute(r));
    if (item.redirect && !item.children.some(ite => ite.path === item.redirect)) {
      routeData.redirect = item.children[0].path;
    }
    if (item.path.includes("fullScreen")) {
      routeData.component = "";
      routeData.redirect = "";
    }
  } else {
    routeData.redirect = "";
  }
  return routeData;
};

const getViceMenu = (item: any) => {
  const { name } = item;
  if (name) {
    const m = viceMenus.find(ite => ite.name === name);
    if (m) {
      // return m.menus;
      return m;
    } else {
      return null;
    }
  }
  return null;
};

/**
 * 将多级嵌套路由处理成一维数组
 * @param routesList 传入路由
 * @returns 返回处理后的一维路由
 */
function formatFlatteningRoutes(routesList: RouteRecordRaw[]) {
  if (routesList.length === 0) return routesList;
  let hierarchyList = buildHierarchyTree(routesList);
  for (let i = 0; i < hierarchyList.length; i++) {
    if (hierarchyList[i].children) {
      hierarchyList = hierarchyList.slice(0, i + 1).concat(hierarchyList[i].children, hierarchyList.slice(i + 1));
    }
  }
  return hierarchyList;
}

/**
 * 一维数组处理成多级嵌套数组（三级及以上的路由全部拍成二级，keep-alive 只支持到二级缓存）
 * @param routesList 处理后的一维路由菜单数组
 * @returns 返回将一维数组重新处理成规定路由的格式
 */
function formatTwoStageRoutes(routesList: RouteRecordRaw[]) {
  if (routesList.length === 0) return routesList;
  const newRoutesList: RouteRecordRaw[] = [];
  routesList.forEach((v: RouteRecordRaw) => {
    if (v.path === "/") {
      newRoutesList.push({
        component: v.component,
        name: v.name,
        path: v.path,
        redirect: v.redirect,
        meta: v.meta,
        children: []
      });
    } else {
      newRoutesList[0]?.children.push({ ...v });
    }
  });
  return newRoutesList;
}

/** 处理缓存路由（添加、删除、刷新） */
function handleAliveRoute({ name }: ToRouteType, mode?: string) {
  switch (mode) {
    case "add":
      usePermissionStoreHook().cacheOperate({
        mode: "add",
        name
      });
      break;
    case "delete":
      usePermissionStoreHook().cacheOperate({
        mode: "delete",
        name
      });
      break;
    case "refresh":
      usePermissionStoreHook().cacheOperate({
        mode: "refresh",
        name
      });
      break;
    default:
      usePermissionStoreHook().cacheOperate({
        mode: "delete",
        name
      });
      useTimeoutFn(() => {
        usePermissionStoreHook().cacheOperate({
          mode: "add",
          name
        });
      }, 100);
  }
}

/** 过滤后端传来的动态路由 重新生成规范路由 */
function addAsyncRoutes(arrRoutes: Array<RouteRecordRaw>) {
  const routes = addAsyncRoutesDefault(arrRoutes);
  initRootRouter(routes);
  return routes;
}

function addAsyncRoutesDefault(arrRoutes: Array<RouteRecordRaw>) {
  if (!arrRoutes || !arrRoutes.length) return;
  const modulesRoutesKeys = Object.keys(modulesRoutes);
  arrRoutes.forEach((v: RouteRecordRaw) => {
    // 将backstage属性加入meta，标识此路由为后端返回路由
    v.meta.backstage = true;
    // 父级的redirect属性取值：如果子级存在且父级的redirect属性不存在，默认取第一个子级的path；如果子级存在且父级的redirect属性存在，取存在的redirect属性，会覆盖默认值
    if (v.redirect && v?.children?.length && !v?.children.some(item => item.path === v.redirect)) v.redirect = v.children[0].path;
    // 父级的name属性取值：如果子级存在且父级的name属性不存在，默认取第一个子级的name；如果子级存在且父级的name属性存在，取存在的name属性，会覆盖默认值（注意：测试中发现父级的name不能和子级name重复，如果重复会造成重定向停用（跳转404），所以这里给父级的name起名的时候后面会自动加上`Parent`，避免重复）
    if (v?.children && v.children.length && !v.name) v.name = (v.children[0].name as string) + "Parent";
    if (v.meta?.frameSrc) {
      v.component = IFrame;
    } else {
      // 对后端传component组件路径和不传做兼容（如果后端传component组件路径，那么path可以随便写，如果不传，component组件路径会跟path保持一致
      const index = v?.component ? modulesRoutesKeys.findIndex(ev => ev.includes(v.component as any)) : -1;

      index > -1 ? (v.component = modulesRoutes[modulesRoutesKeys[index]]) : (v.component = null);
    }
    if (v?.children && v.children.length) {
      v.children = addAsyncRoutesDefault(v.children);
    }
  });
  return arrRoutes;
}

/** 获取路由历史模式 https://next.router.vuejs.org/zh/guide/essentials/history-mode.html */
function getHistoryMode(routerHistory): RouterHistory {
  // len为1 代表只有历史模式 为2 代表历史模式中存在base参数 https://next.router.vuejs.org/zh/api/#%E5%8F%82%E6%95%B0-1
  const historyMode = routerHistory.split(",");
  const leftMode = historyMode[0];
  const rightMode = historyMode[1];
  // no param
  if (historyMode.length === 1) {
    if (leftMode === "hash") {
      return createWebHashHistory("");
    } else if (leftMode === "h5") {
      return createWebHistory("");
    }
  } //has param
  else if (historyMode.length === 2) {
    if (leftMode === "hash") {
      return createWebHashHistory(rightMode);
    } else if (leftMode === "h5") {
      return createWebHistory(rightMode);
    }
  }
}

/** 获取所有菜单中的第一个菜单（顶级菜单）*/
function getTopMenu(tag = false): menuType {
  // const topMenu = usePermissionStoreHook().wholeMenus[0]?.children[0];
  let topMenu = null;
  usePermissionStoreHook().wholeMenus.find(item => {
    const { path, redirect, children } = item;
    if (redirect) {
      if (children?.length) {
        const cp = children.find(ite => ite.path === redirect);
        if (cp) {
          topMenu = cp;
          return true;
        } else {
          return false;
        }
      } else {
        return false;
      }
    } else if (path) {
      topMenu = item;
      return true;
    } else {
      return false;
    }
  });
  // tag && useMultiTagsStoreHook().handleTags("push", topMenu);
  tag && useMultiTagsStoreHook().handleTags("push", getRealTopMenu(topMenu));
  return topMenu;
}

/**
 * @description: 获取真正的第一个路由
 * @param {*} menu
 * @return {*}
 */
function getRealTopMenu(menu) {
  if (!menu) return null;
  const { redirect, children } = menu;
  if (redirect && children?.length) {
    const cp = children.find(item => item.path === redirect);
    if (cp) {
      return cp;
    } else {
      return menu;
    }
  } else {
    return menu;
  }
}

export {
  ascending,
  filterTree,
  initRouter,
  getTopMenu,
  addPathMatch,
  isOneOfArray,
  getHistoryMode,
  addAsyncRoutes,
  getParentPaths,
  findRouteByPath,
  handleAliveRoute,
  formatTwoStageRoutes,
  formatFlatteningRoutes,
  filterNoPermissionTree
};
